#pragma once
#include "xKernel/IxFileManager.h"

[
    default(IxFileManager),
    threading(free),
    uuid("DB6E15E6-B671-49fd-9C63-CB883C1DD536"),
    coclass
]
class ATL_NO_VTABLE CxFileManager : public IxFileManager
{
    typedef std::map<INT, CString>              PATHS;
    typedef PATHS::iterator                     PATHSIT;

    typedef std::map<CString, PATHS>            SYMBOLS;
    typedef SYMBOLS::iterator                   SYMBOLSIT;

public:
    CxFileManager();
    virtual ~CxFileManager();
    DECLARE_PROTECT_FINAL_CONSTRUCT()

public:
    // interface of IxFileManager
    HRESULT RegisterSymbolPath(BSTR bsSymbol, BSTR bsPath, INT nPriority);
    HRESULT UnregisterSymbolPath(BSTR bsSymbol, INT nPriority);
    HRESULT GetBuffer(BSTR bsFile, IxBuffer** ppBuffer);

protected:
    bool    _is_absolute_path(const CString& strPath)
    {
        return (strPath[1] == ':');
    }

    bool    _is_relative_path(const CString& strPath)
    {
        return (-1 == strPath.Find(':'));
    }

    bool    _is_symbol_path(const CString& strPath)
    {
        return (strPath.Find(':') > 1);
    }

    bool    _is_zip_file(const CString& strFile)
    {
        INT nLen = strFile.GetLength();

        // 10 is the minimize length of zip resource path
        if (nLen < 10)
        {
            return false;
        }

        return (strFile[nLen - 1] == 'p') && (strFile[nLen - 2] == 'i') && (strFile[nLen - 3] == 'z') && (strFile[nLen - 4] == '.');
    }

    HRESULT _get_buffer_from_disk(const CString& strFile, IxBuffer** ppBuffer);
    HRESULT _get_buffer_from_zip(const CString& strZipFile, const CString& strFile, IxBuffer** ppBuffer);
    HRESULT _get_buffer_from_pool(const CString& strFile, IxBuffer** ppBuffer);

    bool    _is_file_exist(const CString& bsFile);

protected:
    SYMBOLS     m_mapSymbols;
};